package java6703.task;

import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Optional;
import java.util.Scanner;
import java.util.function.Consumer;

public class Editor6703Controller {
    private File currentFile;
    private SimpleBooleanProperty isChange; //修改标记
    private Alert alert;//是否保存的弹框
    private FileChooser fc;//选择文件对话框

    @FXML
    private TextField tfFilename;

    @FXML
    private TextArea taText;

    @FXML
    private void initialize() {
        //监听TextArea的Text属性被修改的事件
        taText.textProperty().addListener((v1, v2, v3) -> isChange.set(true));//初始化修改标记
        isChange = new SimpleBooleanProperty(false);
        //初始化Alert的基本属性
        alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("文本编辑器提示");
        alert.getButtonTypes().setAll(
                ButtonType.YES,
                ButtonType.NO,
                ButtonType.CANCEL
        );
        //初始化选择文件对话框
        fc = new FileChooser();
        fc.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("文本文件", "*.txt"),
                new FileChooser.ExtensionFilter("Java文件", "*.Java"),
                new FileChooser.ExtensionFilter("所有", "*.*")
        );
    }

    /**
     * 为窗口CloseRequest注册监听，由外部调用*@param stage当前窗口对象Stage
     */
    public void setCloseRequest(Stage stage) {
        //监听请求关闭窗口的事件，即关闭窗口前发生的事件
        stage.setOnCloseRequest(this::beforeClose);
        //监听isChange被修改的事件:一旦修改，在窗口的标题上加星号，表示TextArea中的内容己被修改
        isChange.addListener((v1, v2, newValue) -> stage.setTitle("文本编辑器" + (newValue ? "*" : "")));
    }

    /**
     * 窗口关闭前的处理...
     */
    private void beforeClose(WindowEvent event) {
        if (isChange.get()) {//TextArea中的内容己被修改
            String title = currentFile == null ? "?" : ("到" + currentFile + "?");
            alert.setHeaderText(" 关闭窗口前，是否将未存盘的修改保存 " + title);
            Optional<ButtonType> type = alert.showAndWait();//显示Alert弹窗，并返回关闭弹窗时单击的按钮
            type.ifPresent(new Consumer<ButtonType>() {
                @Override
                public void accept(ButtonType buttonType) {
                    if (buttonType == ButtonType.YES) {
                        //单击是:保存己修改的内容
                        saveFile(null);//调用保存按钮的事件处理方法
                    } else if (buttonType == ButtonType.NO) {
                        //单击否:不保存
                    } else {
                        //单击取消:不能关闭窗口
                        event.consume();
                    }
                }
            });
        }
    }


    @FXML
    void openFile(ActionEvent event) throws FileNotFoundException {
        //打开按钮
        if (!beforeOpenCheck()) {//打开新文件前检查是否有未保存的修改
            return;
        }
        setFileChooser("打开");//设置选择文件对话框的标题和初始目录
        File newFile = fc.showOpenDialog(new Stage());//打开选择文件对话框，并返回选择的文件
        // 如果没有选择要打开的文件，维持原样，currentFile不能改变
        if (newFile != null) {
            //选择了新文件
            currentFile = newFile;
            tfFilename.setText(currentFile.toString());//显示当前编辑的文件名open(currentFile);//读取文件内容并显示到TextArea
            open(currentFile);
            isChange.set(false); //重置修改状态
        }
    }

    /**
     * 设置选择文件对话框的标题和初始目录
     */
    private void setFileChooser(String title) {
        fc.setTitle(title);
        if (currentFile == null) {
            fc.setInitialDirectory(new File("."));
        } else {
            //初始目录，使用当前文件所在目录
            fc.setInitialDirectory(currentFile.getParentFile());
        }
    }


    /**
     * 打开新文件前，处理已修改但未保存的内容，处理后才能打开新文件*areturn如果己处理返回true，否则返回false
     */
    private boolean beforeOpenCheck() {
        boolean isOpen = true;
        if (isChange.get()) {
            String title = currentFile == null ? "?" : ("到" + currentFile + "?");
            alert.setHeaderText("打开新文件前，是否将未存盘的修改保存" + title);
            Optional<ButtonType> type = alert.showAndWait();//显示ALert弹窗，并返回关闭弹窗时单击的按钮
            if (type.isPresent()) {
                ButtonType buttonType = type.get();
                if (buttonType == ButtonType.YES) {
                    //先保存，再打开
                    saveFile(null); //调用保存按钮的事件处理方法
                } else if (buttonType == ButtonType.NO) {
                    //不保存，直接打开
                } else {
                    //取消打开的动作
                    isOpen = false;
                }
            }
        }
        return isOpen;
    }

    /**
     * 将文件内容显示到TextArea ...
     */
    private void open(File file) throws FileNotFoundException {
        //使用Scanner读文本文件
        try (Scanner reader = new Scanner(file)) {
            StringBuilder sBuilder = new StringBuilder();
            while (reader.hasNextLine()) {
                sBuilder.append(reader.nextLine()).append(System.lineSeparator());
            }
            taText.setText(sBuilder.toString());
        } catch (FileNotFoundException e) {
            throw e;
        }
    }

    @FXML
    void saveAsFile(ActionEvent event) {
        //另存按钮
        setFileChooser("另存为");//设置选择文件对话框的标题和初始目录
        File asFile = fc.showSaveDialog(new Stage());//打开选择文件对话框，并返回选中的文件
        save(asFile);//另存，改变当前文件以及修改状态

    }

    private void save(File file) {
        if (file == null) return;
        try (PrintWriter pw = new PrintWriter(file)) {
            pw.print(taText.getText());
            isChange.set(false);
            currentFile = file;
            //显示当前编辑的文件名
            tfFilename.setText(currentFile.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    @FXML
    void saveFile(ActionEvent event) {
        //保存按钮
        if (currentFile == null) {//新建文件，将打开选择文件对话框
            setFileChooser("保存为");//设置选择文件对话框的标题和初始目录
            // 打开选择文件对话框，并返回选择的文件
            File file = fc.showSaveDialog(new Stage());
            save(file);
        } else {
            save(currentFile);
        }

    }

}